package QC.MessageBox.handler;

import QC.MessageBox.annotation.MethodLog;
import QC.MessageBox.annotation.RouteMapping;
import QC.MessageBox.beans.*;
import QC.MessageBox.beans.appmsg.BaseAppMsg;
import QC.MessageBox.beans.appmsg.ExtraMsg;
import QC.MessageBox.beans.rcform.RCOnlineStatu;
import QC.MessageBox.beans.rcform.RCSingleForm;
import QC.MessageBox.beans.wbmsg.WBTextMsg;
import QC.MessageBox.beans.wbmsg.back.WBArticle;
import QC.MessageBox.beans.wbmsg.back.WBArticlesMsg;
import QC.MessageBox.beans.webmsg.WebRCMsg;
import QC.MessageBox.beans.webmsg.WebUserExtra;
import QC.MessageBox.common.HttpUtils;
import QC.MessageBox.common.PeriodicTime;
import QC.MessageBox.enums.ActiveLimit;
import QC.MessageBox.enums.ChannelType;
import QC.MessageBox.enums.SendResult;
import QC.MessageBox.enums.SourceType;
import QC.MessageBox.service.*;
import io.vertx.core.CompositeFuture;
import io.vertx.core.Future;
import io.vertx.core.http.HttpMethod;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.http.HttpServerResponse;
import io.vertx.core.json.Json;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.RoutingContext;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.stream.Collectors;


/**
 * Created by Andaren on 2017/6/29.
 * Used for: 网页回复
 */
@RouteMapping(path = "/web/message")
public class WebTalkWindowHandler extends HandlerBase {

    private static final Logger LOGGER = LoggerFactory.getLogger(WebTalkWindowHandler.class);

    private BlockingService blockingService;

    public WebTalkWindowHandler() {}

    public WebTalkWindowHandler(Map<String, Object> handlerMap) {
        Objects.requireNonNull(handlerMap);
        this.dataAccess = (DataAccess)handlerMap.get("dataAccess");
        this.httpService = (HttpService)handlerMap.get("httpService");
        this.sqlService = (MySQLService)handlerMap.get("mySQLService");
        this.redisService = (RedisService)handlerMap.get("redisService");
//        this.mongoService = (MongoService) handlerMap.get("mongoService");
        this.webClientService = (WebClientService)handlerMap.get("webClientService");
        this.blockingService = (BlockingService)handlerMap.get("blockingService");
    }

//    @RouteMapping(path = "/send")
//    @MethodLog("web talk handler")
//    public void handleWebMsg (RoutingContext context) {
//        HttpServerRequest appRequest = context.request();
//        HttpServerResponse appResponse = context.response();
//        String method = "result";
//        final String successResult = "{result:1}";
//        final String failedResult = "{result:0}";
//
//        LOGGER.info("[received web msg={}]", appRequest.getParam("content"));
//
//        if(checkRequestParamInRequest(appRequest)) {
//            final WebRCMsg webMsg = new WebRCMsg();
//            webMsg.setDeveloperId(appRequest.getParam("developerId"))
//                    .setContent(appRequest.getParam("content"))
//                    .setFromUser(appRequest.getParam("fromUser"))
//                    .setType(appRequest.getParam("type"))
//                    .setExtra(appRequest.getParam("extra"));
//
//            Future<Void> sendFut = Future.future();
//            dataAccess.checkWebUser(webMsg.getFromUser())
//                    .compose(csChatIdOp -> {
//                        if (csChatIdOp.isPresent() && csChatIdOp.get().getPulledBlack()) {
//                            // 被拉黑则消息不处理
//                            sendFut.complete();
//                        }
//                        Future<WebUserMap> csChatIdFut = Future.future();
//                        if (csChatIdOp.isPresent()) {
//                            csChatIdFut.complete(csChatIdOp.get());
//                        } else {
//                            webClientService.getCustomerServerByOpenidFromAppBack(webMsg.getFromUser(), webMsg.getDeveloperId(), ChannelType.WEB.val())
//                                    .compose(appUser -> {
//                                        WebUserMap webUserMap = new WebUserMap();
//                                        webUserMap.setPulledBlack(false)
//                                                .setCsChatId(appUser.getTalkId());
//                                        csChatIdFut.complete(webUserMap);
//                                    }, csChatIdFut);
//                        }
//                        return csChatIdFut;
//                    })
//                    .compose(webUserInfo -> {
//                        String csChatId = webUserInfo.getCsChatId();
//                        Future<RCSingleForm> formMsgFur = Future.future();
//                        // 生成消息数据
//                        final ExtraMsg extraMsg;
//                        if (webMsg.getExtra() != null) {
//                            // 生成消息数据
//                            extraMsg = Json.decodeValue(webMsg.getExtra(), ExtraMsg.class);
//                            extraMsg.setDeveloperId(webMsg.getDeveloperId())
//                                    .setOpenId(webMsg.getFromUser())// 暂时无用
//                                    .setType(SourceType.WX.val())
//                                    .setChannelType(ChannelType.WEB.val())
//                                    .setTimestamp(String.valueOf(PeriodicTime.getCurrentTimestamp()));
//                        } else {
//                            extraMsg = new ExtraMsg();
//                        }
//                        RCSingleForm singleForm = new RCSingleForm();
//                        if ("text".equals(webMsg.getType())) { // 文本消息
//                            JsonObject msgJson = new JsonObject();
//                            msgJson.put("content", webMsg.getContent())
//                                    .put("extra", Json.encode(extraMsg));
//
//                            singleForm.setFromUserId(webMsg.getFromUser())
//                                    .setToUserId(csChatId)
//                                    .setObjectName(WeiBoHandler.RCMsgType.TEXT.val())
//                                    .setContent(msgJson.encodePrettily());
//                            formMsgFur.complete(singleForm);
//                        } else if ("image".equals(webMsg.getType())) {  // 图片消息
//                            blockingService.getImageInfoByUrl(webMsg.getContent())
//                                    .compose(imageInfo -> {
//                                        JsonObject msgJson = new JsonObject();
//                                        msgJson.put("content", imageInfo.toJson().encode())
//                                                .put("imageUri", webMsg.getContent())
//                                                .put("extra", Json.encode(extraMsg));
//                                        singleForm.setFromUserId(webMsg.getFromUser())
//                                                .setToUserId(csChatId)
//                                                .setObjectName(WeiBoHandler.RCMsgType.IMAGE.val())
//                                                .setContent(msgJson.encodePrettily());
//                                        formMsgFur.complete(singleForm);
//                                    }, formMsgFur);
//                        } else {
//                            LOGGER.info("不支持的消息类型-> \n{}", Json.encodePrettily(webMsg));
//                            sendFut.fail("不支持的消息类型");
//                        }
//                        return formMsgFur;
//                    })
//                    .compose(singleForm -> {
//                        WebUserMap webUserMap = new WebUserMap();
//                        webUserMap.setPulledBlack(false)
//                                .setCsChatId(singleForm.getToUserId());
//                        redisService.set(RedisService.REDIS_KEY_WEB_USER_CHAT_ID+":"+singleForm.getFromUserId(), Json.encode(webUserMap))
//                                .compose(webUserSaved -> {
//                                    sendSingMsgToRC(singleForm, sendFut);
//                                }, sendFut);
//                    }, sendFut);
//
//            sendFut.setHandler(ar -> {
//                if (ar.failed()) {
//                    LOGGER.info("send fail error=[{}]", ar.cause().getMessage());
//                    // 日常返回
//                    appResponse
//                            .putHeader("content-type", "text/html; charset=UTF-8")
//                            .putHeader("Access-Control-Allow-Origin", "*")
//                            .end(method+"("+failedResult+")");
//                } else {
//                    LOGGER.info("web msg send success");
//                    // 日常返回
//                    appResponse
//                            .putHeader("content-type", "text/html; charset=UTF-8")
//                            .putHeader("Access-Control-Allow-Origin", "*")
//                            .end(method+"("+successResult+")");
//                }
//            });
//        } else {
//            // 日常返回
//            appResponse
//                    .putHeader("content-type", "text/html; charset=UTF-8")
//                    .putHeader("Access-Control-Allow-Origin", "*")
//                    .end(method+"("+failedResult+")");
//        }
//
//    }

    @RouteMapping(path = "/send")
    @MethodLog("web talk handler version 2")
    public void handleWebMsgForV2 (RoutingContext context) {
        HttpServerRequest appRequest = context.request();
        HttpServerResponse appResponse = context.response();
        String method = "result";
        final String successResult = "{result:1}";
        final String failedResult = "{result:0}";

        LOGGER.info("[received web msg={}]", appRequest.getParam("content"));

        if(checkRequestParamInRequest(appRequest)) {
            final WebRCMsg webMsg = new WebRCMsg();
            webMsg.setDeveloperId(appRequest.getParam("developerId"))
                    .setContent(appRequest.getParam("content"))
                    .setFromUser(appRequest.getParam("fromUser"))
                    .setType(appRequest.getParam("type"))
                    .setExtra(appRequest.getParam("extra"));
            // Web消息额外的必须信息
            final WebUserExtra webUserExtra = Json.decodeValue(webMsg.getExtra(), WebUserExtra.class);

            Future<Void> sendFut = Future.future();
//            dataAccess.checkChannelUserPulledBlack(webMsg.getFromUser()).toString()
            dataAccess.checkWebUser(webMsg.getFromUser())
                    .compose(csChatIdOp -> {
                        if (csChatIdOp.isPresent() && csChatIdOp.get().getPullBlack() == 1) {
                            // 被拉黑则消息不处理
                            sendFut.complete();
                        }
                        Future<Void> csChatIdFut = Future.future();
                        if (csChatIdOp.isPresent()) {
                            final AppUser appUser = csChatIdOp.get();
                            /**
                             * 缓存命中：保存聊天记录，更新用户状态
                             *
                             * 比较这次Web粉丝的融云talkId和数据库里的融云talkId,
                             * 如果不相同，则更新为新的talkId
                             */
                            dataAccess.findWxUserByOpenId(webUserExtra.getPhone())
                                    .compose(wxUser -> {
                                        List<Future> futList = new ArrayList<>();
                                        if (wxUser.getUnionid() != null && !webMsg.getFromUser().equals(wxUser.getUnionid())) {
                                            // 不相同，则更新为新的talkId
                                            wxUser.setUnionid(webMsg.getFromUser());
                                            // 更新缓存
                                            Future<Void> updateRedisFut =
                                                    redisService.set(RedisService.REDIS_KEY_WX_USER+":"+webUserExtra.getPhone(), Json.encode(wxUser));
                                            // 更新数据库
                                            Future<Void> updateDBFut =
                                                    sqlService.updateWebFansTalkByPhone(webUserExtra.getPhone(), wxUser.getUnionid(), webMsg.getFromUser());
                                            futList.add(updateRedisFut);
                                            futList.add(updateDBFut);
                                        }
                                        return CompositeFuture.all(futList);
                                    })
                                    .compose(compositeFuture -> {
                                        csChatIdFut.complete();
                                    }, csChatIdFut);
                        } else {
                            /**
                             * 缓存未命中：进行新增用户流程，同上
                             */
                            WXUser webUser = new WXUser();
                            webUser.setCreateTime(PeriodicTime.getCurrentTimestampStr())
                                    .setWxOpenId(webUserExtra.getPhone())
                                    .setUnionid(webMsg.getFromUser()) // 粉丝通信talkId
                                    .setWxNickName("网页客户");
                            dataAccess.getWXPublicInfoByDeveloperId(webMsg.getDeveloperId())
                                    .compose(wxPub ->
                                            // 新增粉丝流程
                                        insertNewWebFans(webUser, webMsg, wxPub))
                                    .compose(webUserInserted -> {
                                        csChatIdFut.complete();
                                    }, csChatIdFut);
                        }
                        return csChatIdFut;
                    })
                    .compose(webFansChecked -> {
                        // 发送消息
                        sendWebMsgToCS(webMsg, webUserExtra).setHandler(sendFut.completer());
                    }, sendFut);

            sendFut.setHandler(ar -> {
                if (ar.failed()) {
                    LOGGER.info("send fail error=[{}]", ar.cause().getMessage());
                    // 日常返回
                    appResponse
                            .putHeader("content-type", "text/html; charset=UTF-8")
                            .putHeader("Access-Control-Allow-Origin", "*")
                            .end(method+"("+failedResult+")");
                } else {
                    LOGGER.info("web msg send success");
                    // 日常返回
                    appResponse
                            .putHeader("content-type", "text/html; charset=UTF-8")
                            .putHeader("Access-Control-Allow-Origin", "*")
                            .end(method+"("+successResult+")");
                }
            });
        } else {
            // 日常返回
            appResponse
                    .putHeader("content-type", "text/html; charset=UTF-8")
                    .putHeader("Access-Control-Allow-Origin", "*")
                    .end(method+"("+failedResult+")");
        }

    }

    /**
     * web粉丝发送消息给客服
     * @param webMsg
     * @param webUserExtra
     * @return
     * @throws Exception
     */
    public Future<Void> sendWebMsgToCS(WebRCMsg webMsg, WebUserExtra webUserExtra) {
        Future<Void> textMsgHandlerFut = Future.future();

        // 获取APP用户对应的talkId
        Future<AppUser> appUserFut = dataAccess.getAppUser(webUserExtra.getPhone());
        // 获取用户信息
        Future<WXUser> wxUserFuture = dataAccess.findWxUserByOpenId(webUserExtra.getPhone());
        // 获取公众号信息
        Future<WXPublic> pubFuture = dataAccess.getWXPublicInfoByDeveloperId(webMsg.getDeveloperId());

        CompositeFuture.all(appUserFut, wxUserFuture, pubFuture).setHandler(comAs -> {
            if (comAs.failed()) {
                textMsgHandlerFut.fail(comAs.cause());
            } else {
                AppUser appUser = comAs.result().resultAt(0);
                WXUser wxUser = comAs.result().resultAt(1);
                WXPublic wxPublic = comAs.result().resultAt(2);
                final String openId = webUserExtra.getPhone();
                final String developerId = webMsg.getDeveloperId();
                final String csChatId = appUser.getTalkId();
                final String fansChatId = wxUser.getUnionid();

                // 生成消息数据
                RCSingleForm singleForm = new RCSingleForm();
                Future<RCSingleForm> formMsgFur = Future.future();
                ExtraMsg extraMsg = new ExtraMsg();
                extraMsg.setDeveloperId(developerId)
                        .setHeadUrl(wxUser.getHeadUrl() == null ? "" : wxUser.getHeadUrl())
                        .setNickName(wxUser.getWxNickName() == null ? "" : wxUser.getWxNickName())
                        .setPublicName(wxPublic.getName() == null ? "" : wxPublic.getName())
                        .setOpenId(openId)
                        .setType(SourceType.WX.val())
                        .setChannelType(ChannelType.WEB.val())
                        .setTimestamp(PeriodicTime.getCurrentTimestampStr());
                JsonObject msgJson = new JsonObject();
                if ("text".equals(webMsg.getType())) { // 文本消息
                    msgJson.put("content", webMsg.getContent())
                            .put("extra", Json.encode(extraMsg));

                    singleForm.setFromUserId(fansChatId)
                            .setToUserId(csChatId)
                            .setObjectName(WeiBoHandler.RCMsgType.TEXT.val())
                            .setContent(msgJson.encodePrettily());
                    formMsgFur.complete(singleForm);
                } else if ("image".equals(webMsg.getType())) {  // 图片消息
                    blockingService.getImageInfoByUrl(webMsg.getContent())
                            .compose(imageInfo -> {
                                msgJson.put("content", imageInfo.toJson().encode())
                                        .put("imageUri", webMsg.getContent())
                                        .put("extra", Json.encode(extraMsg));
                                singleForm.setFromUserId(webMsg.getFromUser())
                                        .setToUserId(csChatId)
                                        .setObjectName(WeiBoHandler.RCMsgType.IMAGE.val())
                                        .setContent(msgJson.encodePrettily());
                                formMsgFur.complete(singleForm);
                            }, formMsgFur);
                }

                //-----------------------------------------------------------
                // 记录消息
                MsgRecord msgRecord = new MsgRecord();
                msgRecord.setOpenId(openId)
                        .setMsgType(webMsg.getType())
                        .setSourceType(MsgRecord.MSG_FROM_WX)
                        .setContent(msgJson.toString())
                        .setCsId(appUser.getCsId())
                        .setCsNickName(appUser.getNickname())
                        .dropEmoji()
                        .setIsRead("0")
                        .setSendtime(PeriodicTime.getCurrentTimestamp());

                // 保存消息记录
                sqlService.save(msgRecord)
                        .compose(newMsgRecord -> {
                            // 更新互动时间
                            return sqlService.updateUserLimit(openId, new EnumMap<ActiveLimit, Long>(ActiveLimit.class){
                                {
                                    put(ActiveLimit.ACTIVE_LIMIT, PeriodicTime.getCurrentTimestamp());
                                    put(ActiveLimit.LATELY_MSG_ID, newMsgRecord.getId());
                                }
                            });
                        })
                        .compose( (Void) -> {
                            // 发送消息至融云平台
                            sendSingMsgToRC(singleForm, textMsgHandlerFut);
                        }, textMsgHandlerFut);
            }
        });
        return textMsgHandlerFut;
    }

    /**
     * [ {
     "userid" : "1658806157",
     "status" : "0",
     "os" : "iOS",
     "time" : 1510042398702
     } ]
     * @param context
     */
    @RouteMapping(path = "/rc/online/status", method = HttpMethod.POST)
    @MethodLog("融云用户在线状态订阅")
    public void receiveRCOnlineStatusMsg(RoutingContext context) {
        HttpServerRequest rcRequest = context.request();
        HttpServerResponse rcResponse = context.response();
        /**
         * 同步在线状态时都需要你的服务提供应答，只要有应答 200 ，就表示状态已经同步
         *      如果应答超时 5 秒，融云会再尝试推送 2 次，如果仍然失败，融云将不再同步此条状态。
         *      如短时间内有大面积超时，将暂停推送，1 分钟后会继续推送。异常断网情况下的在线状态会延迟 5 分钟同步。
         */
        rcResponse.end("200");

        /**
         * 以下为正常业务处理
         */
        // 融云用户在线状态列表
        JsonArray userStatusArray = context.getBodyAsJsonArray();
        LOGGER.info("接收到融云在线状态推送：\n{}", userStatusArray.encodePrettily());
        List<RCOnlineStatu> rcOnlineStatuList = Collections.emptyList();
        rcOnlineStatuList = userStatusArray.stream()
                .map(j -> new RCOnlineStatu((JsonObject) j))
                .collect(Collectors.toList());

        for (RCOnlineStatu fansOnline : rcOnlineStatuList) {
            Future<Void> updateFansOnlineStautFut = Future.future();
            sqlService.getWxUserByUnionId(fansOnline.getUserid())
                    .compose(wxUser -> {
                        if ("0".equals(fansOnline.getStatus())) {
                            // 用户上线通知
                            sqlService.updateWebFansOnlineStatus(wxUser.getWxOpenId(), true)
                                    .setHandler(updateFansOnlineStautFut.completer());
                        } else {
                            // 用户下线通知
                            sqlService.updateWebFansOnlineStatus(wxUser.getWxOpenId(), false)
                                    .setHandler(updateFansOnlineStautFut.completer());
                        }
                    }, updateFansOnlineStautFut);
            updateFansOnlineStautFut.setHandler(ar -> {
               if (ar.succeeded()) {
                   LOGGER.info(">>>>>>用户[{}][{}]了.",
                           fansOnline.getUserid(),
                           "0".equals(fansOnline.getStatus())?"上线了":"下线了");
               } else {
                   LOGGER.error("融云在线状态推送处理异常：{}", ar.cause().getMessage());
               }
            });
        }
    }

    /**
     * 当web粉丝进入/退出网页聊天时，更新粉丝在线状态
     * @param context
     */
    @RouteMapping(path = "/rc/online/status")
    @MethodLog("web粉丝在线/离线")
    public void dealWebFansLeave(RoutingContext context) {
        HttpServerRequest appRequest = context.request();
        HttpServerResponse appResponse = context.response();
        String method = "result";
        final String successResult = "{result:1}";
        final String failedResult = "{result:0}";

        LOGGER.info("[update fans status ->phone={}]", appRequest.getParam("fansPhone"));
        String fansPhone = appRequest.getParam("fansPhone");
        String onlineStatus = appRequest.getParam("onlineStatus");

        if(StringUtils.isNotBlank(fansPhone) && StringUtils.isNotBlank(onlineStatus)) {
            Future<Void> updateStatusFut = Future.future();
            redisService.get(RedisService.REDIS_KEY_WEB_USER_CHAT_ID+":"+fansPhone)
                    .compose(webUserMapStr -> {
                        if (webUserMapStr == null) {
                            LOGGER.error("Redis中找不到该电话对应的web粉丝信息：phone={}", fansPhone);
//                            updateStatusFut.fail("Redis中找不到该电话对应的web粉丝信息");
                            updateStatusFut.complete();
                        }
                        WebUserMap webUserMap = Json.decodeValue(webUserMapStr, WebUserMap.class);
                        webUserMap.setOnlineStatus(Boolean.valueOf(onlineStatus));

                        dataAccess.updateWebFansOnline(webUserMap)
                                .setHandler(updateStatusFut.completer());
                    }, updateStatusFut);
            updateStatusFut.setHandler(ar -> {
                if (ar.failed()) {
                    LOGGER.info("send fail error=[{}]", ar.cause().getMessage());
                    // 日常返回
                    appResponse
                            .putHeader("content-type", "text/html; charset=UTF-8")
                            .putHeader("Access-Control-Allow-Origin", "*")
                            .end(method+"("+failedResult+")");
                } else {
                    LOGGER.info("更新Web粉丝状态完成");
                    // 日常返回
                    appResponse
                            .putHeader("content-type", "text/html; charset=UTF-8")
                            .putHeader("Access-Control-Allow-Origin", "*")
                            .end(method+"("+successResult+")");
                }
            });
        } else {
            // 日常返回
            appResponse
                    .putHeader("content-type", "text/html; charset=UTF-8")
                    .putHeader("Access-Control-Allow-Origin", "*")
                    .end(method+"("+failedResult+")");
        }
    }

    /**
     * 新增web粉丝
     * @param webUser
     * @param webRCMsg
     * @param wxPublic
     * @return
     * @throws Exception
     */
    public Future<Void> insertNewWebFans(WXUser webUser, WebRCMsg webRCMsg, WXPublic wxPublic) {
        Future<Void> subscribeMsgHandlerFut = Future.future();

        final String developerId = webRCMsg.getDeveloperId();
        final String wxOpenId = webUser.getWxOpenId();
        Future<AppUser> csUserFuture = webClientService.getCustomerServerByOpenidFromAppBack(
                webUser.getWxOpenId(),
                webRCMsg.getDeveloperId(),
                ChannelType.WEB.val()
        );//Future.succeededFuture(new AppUser());//
//        CompositeFuture.all(csUserFuture)
        csUserFuture
                .compose(appUser -> {
                    appUser.setChannelType(ChannelType.WEB.val());
                    // 保存微博用户信息
                    Future<WXUser> saveWxUserFuture = dataAccess.insertWxUser(webUser);
                    // 保存用户映射
                    Future<AppUser> appUserFuture = dataAccess.saveAppUser(appUser);
                    // 通知app后台有新用户生成
                    Future<Void> sendUserFuture = webClientService.sendNewWXUserToAppBack(webUser, appUser.getCsId(), ChannelType.WEB.val());
                    // 获取微官网信息
//                    Future<JsonObject> microwebsiteFuture = webClientService.getMicroWebSiteInfo(wxSubcribeMsg.getToUserName(), appUser.getCsId());
                    // 生成用户互动限制
                    UserLimit newUserLimit = new UserLimit();
                    newUserLimit.setDeveloperId(developerId)
                            .setOpenId(wxOpenId)
                            .setLaseSendTimestamp(PeriodicTime.getCurrentTimestamp())
                            .setPicLimit(ActiveLimit.PIC_LIMIT.getLimit())
                            .setTextLimit(100)// WEB粉丝在线状态->100标识在线，0：标识离线
                            .setPicTextLimt(ActiveLimit.PIC_TEXT_LIMIT.getLimit());
                    // 先查找用户之前最后一次聊天，再将其赋值给LatelyMsgId
                    Future<UserLimit> saveUserLimit = sqlService.findLastSendMsgByOpenId(webUser.getWxOpenId())
                            .compose(lastMsg -> {
                                newUserLimit.setLatelyMsgId(lastMsg.getId()==null?0L:lastMsg.getId());
                                return sqlService.save(newUserLimit);
                            });
                    // 生成客服服务数据记录
                    CusServiceData cusServiceData = new CusServiceData();
                    cusServiceData.setActiveCount(0L)
                            .setCsId(appUser.getCsId())
                            .setCreateTime(PeriodicTime.getCurrentTimestamp())
                            .setCurrentUse("0")
                            .setDeveloperId(developerId)
                            .setOpenId(wxOpenId);
                    Future<CusServiceData> saveCusServDateFut = sqlService.save(cusServiceData);
                    //                                ,      microwebsiteFuture,
                    return CompositeFuture.all(saveWxUserFuture, appUserFuture, sendUserFuture, saveUserLimit, saveCusServDateFut);
                })
                .compose( compositeFutureAsyncResult -> {

                    WXUser wxUser = compositeFutureAsyncResult.result().resultAt(0);
                    AppUser appUser = compositeFutureAsyncResult.result().resultAt(1);
                    JsonObject micorInfo = null;//new JsonObject();// compositeFutureAsyncResult.result().resultAt(3);

                    // 记录用户关注
                    UserAction userAction = new UserAction();
                    userAction.setOpenId(wxOpenId)
                            .setActStartTime(PeriodicTime.getCurrentTimestamp())
                            .setActType("SUBSCRIBE")
                            .setDescription("关注了公众号");
                    Future saveUserActionFut = sqlService.save(userAction);

                    Future<Void> replyPicTextFut = Future.future();
                    if (micorInfo == null) {
                        replyPicTextFut.complete();
                    } else {
                        // 返回图文消息
                        WBArticle article = new WBArticle();
                        article.setDisplay_name("测试图文")
                                .setImage("http://storage.mcp.weibo.cn/0JlIv.jpg")
                                .setSummary("这种图文可以带外链")
                                .setUrl("http://www.cnitr.net/");
                        List<WBArticle> articleList = new ArrayList<>();
                        articleList.add(article);
                        WBArticlesMsg wbArticlesMsg = new WBArticlesMsg();
                        wbArticlesMsg.setArticleList(articleList);

                        WBTextMsg articleMsg = new WBTextMsg();
                        articleMsg.setData(wbArticlesMsg.toJsonString())
                                .setAccess_token(wxPublic.getAccessToken())
                                .setReceiver_id(Long.valueOf(developerId))
                                .setType("articles");
                        replyPicTextFut = webClientService.sendMsgToFans(wxPublic.getAccessToken(), articleMsg);
                    }
                    //客服问候语
                    Future<String> greetingFut = webClientService.getCSGreetingByCsId(Integer.valueOf(appUser.getCsId()));
                    CompositeFuture.all(saveUserActionFut, replyPicTextFut,greetingFut)
                            .compose(compositeFutureAr -> {
                                // 返回文字问候
                                String greetingWords = compositeFutureAr.resultAt(2).toString();
                                // 发送融云消息
                                ExtraMsg extraMsg = new ExtraMsg();
                                extraMsg.setDeveloperId(wxPublic.getDeveloperId())
                                        .setHeadUrl(wxUser.getHeadUrl() == null ? "" : wxUser.getHeadUrl())
                                        .setNickName(wxUser.getWxNickName() == null ? "" : wxUser.getWxNickName())
                                        .setPublicName(wxPublic.getName() == null ? "" : wxPublic.getName())
                                        .setOpenId(wxUser.getWxOpenId())
                                        .setType(SourceType.WX.val())
                                        .setChannelType(ChannelType.WEB.val())
                                        .setTimestamp(PeriodicTime.getCurrentTimestampStr());
                                JsonObject msgJson = new JsonObject();
                                msgJson.put("content", greetingWords)
                                        .put("extra", Json.encode(extraMsg));

                                RCSingleForm singleForm = new RCSingleForm();
                                singleForm.setFromUserId(webUser.getUnionid())  // 粉丝的talkId
                                        .setToUserId(appUser.getTalkId())       // 客服的talkId
                                        .setObjectName(WXHandler.RCMsgType.TEXT.val())
                                        .setContent(msgJson.encodePrettily());
                                Future<Void> notifyCsFut = Future.future();
                                // 发送消息至融云平台
                                sendSingMsgToRC(singleForm, notifyCsFut);
                                return notifyCsFut;
                            })
                            .compose(replyAr -> {
                                subscribeMsgHandlerFut.complete();
                            }, subscribeMsgHandlerFut);
                }, subscribeMsgHandlerFut);
        return subscribeMsgHandlerFut;
    }

    /**
     * 检验请求参数
     * @param request
     * @return
     */
    public boolean checkRequestParamInRequest(HttpServerRequest request) {
        if (StringUtils.isBlank(request.getParam("fromUser"))) {
            return false;
        } else if (StringUtils.isBlank(request.getParam("type"))) {
            return false;
        } else if (StringUtils.isBlank(request.getParam("developerId"))) {
            return false;
        } else if (StringUtils.isBlank(request.getParam("content"))) {
            return false;
        }
        return true;
    }

    /**
     * 检验请求参数
     * @param appResponse
     * @param baseAppMsg
     * @return
     */
    public boolean checkRequestParam(HttpServerResponse appResponse, BaseAppMsg baseAppMsg) {
        if (StringUtils.isBlank(baseAppMsg.getOpenId())) {
            HttpUtils.commonJsonResponse(appResponse, SendResult.FAILED_PARAM.getResultJson("openId为空"));
            return false;
        } else if (StringUtils.isBlank(baseAppMsg.getDeveloperId())) {
            HttpUtils.commonJsonResponse(appResponse, SendResult.FAILED_PARAM.getResultJson("developerId为空"));
            return false;
        } else if (StringUtils.isBlank(baseAppMsg.getType())) {
            HttpUtils.commonJsonResponse(appResponse, SendResult.FAILED_PARAM.getResultJson("type为空"));
            return false;
        } else if (StringUtils.isBlank(baseAppMsg.getContent())) {
            HttpUtils.commonJsonResponse(appResponse, SendResult.FAILED_PARAM.getResultJson("content为空"));
            return false;
        }
        return true;
    }

}
